home *** CD-ROM | disk | FTP | other *** search
/ CDUTIL 13 / CDUTIL #13 Julio 1995.iso / windows / acadcom / ads / sample / callex.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-08  |  12.3 KB  |  449 lines

  1. /* Next available MSG number is     1 */
  2.  
  3. /*****************************************************************************
  4.       CALLEX.C
  5.       (C) Copyright 1988-1994 by Autodesk, Inc.
  6.  
  7.       This program is copyrighted by Autodesk, Inc. and is  licensed
  8.       to you under the following conditions.  You may not distribute
  9.       or  publish the source code of this program in any form.   You
  10.       may  incorporate this code in object form in derivative  works
  11.       provided  such  derivative  works  are  (i.) are  designed and
  12.       intended  to  work  solely  with  Autodesk, Inc. products, and
  13.       (ii.)  contain  Autodesk's  copyright  notice  "(C)  Copyright
  14.       1988-1993 by Autodesk, Inc."
  15.  
  16.       AUTODESK  PROVIDES THIS PROGRAM "AS IS" AND WITH  ALL  FAULTS.
  17.       AUTODESK  SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF  MER-
  18.       CHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK,  INC.
  19.       DOES  NOT  WARRANT THAT THE OPERATION OF THE PROGRAM  WILL  BE
  20.       UNINTERRUPTED OR ERROR FREE.
  21.  
  22.   Description: Lexical analyser for the Geometry Calculator ADS application.
  23.  
  24. *****************************************************************************/
  25.  
  26.  
  27. /****************************************************************************/
  28. /*  INCLUDES                                                                */
  29. /****************************************************************************/
  30.  
  31. #define MODULE_ID CALLEX_C_
  32.  
  33. #include "cal.h"
  34.  
  35. #include "xmf.h"
  36. #include "ads_ix.h"
  37.  
  38.  
  39. /****************************************************************************/
  40. /*  EXPORTED VARIABLES                                                      */
  41. /****************************************************************************/
  42.  
  43. lex_output_type cal_lex;              /* Output from the lexical analyser */
  44.  
  45.  
  46. /****************************************************************************/
  47. /*  STATIC VARIABLES AND FUNCTIONS                                          */
  48. /****************************************************************************/
  49.  
  50. /* Keyword table */
  51.  
  52. static struct {char *ident; symbol_type symbol;} kw[] =
  53. {
  54.     /*MSG0*/"PI",      pi_sym,
  55.     /*MSG0*/"GETVAR",  getvar_sym,
  56.     /*MSG0*/"CVUNIT",  cvunit_sym,
  57. };
  58.  
  59. #define NKWS  ELEMENTS(kw)            /* Number of keywords */
  60.  
  61. static char ch;                       /* The current character         */
  62. static char *ch_ptr;                  /* Pointer to the next character */
  63. static int  end_of_line;              /* TRUE=next_char() reached EOLN */
  64.  
  65. static void        str_toupper          _((char *str));
  66. static symbol_type is_keyword           _((char *ident));
  67. static void        next_char            _((void));
  68. static void        number               _((void));
  69. static void        number_angle_or_feet _((void));
  70.  
  71.  
  72. /****************************************************************************/
  73. /*.doc str_toupper(internal)*/
  74. /*+
  75.   Converts the given string to upper case (I cannot understand why this is
  76.   not a standard function somewhere in a standard library).
  77. -*/
  78. /****************************************************************************/
  79.  
  80.  
  81. static void
  82. /*FCN*/str_toupper(str)
  83.  
  84.   char *str;
  85. {
  86.     while ((*str = ads_toupper(*str)) != 0) {
  87.         str++;
  88.     }
  89. } /*str_toupper*/
  90.  
  91.  
  92. /****************************************************************************/
  93. /*.doc is_keyword(internal)*/
  94. /*+
  95.   Returns the keyword symbol if the given identitier is a keyword or
  96.   symbol 'ident_sym' if it is not.
  97. -*/
  98. /****************************************************************************/
  99.  
  100.  
  101. static symbol_type
  102. /*FCN*/is_keyword(ident)
  103.  
  104.   char *ident;
  105. {
  106.     register int i;
  107.  
  108.     for (i = 0; i < NKWS; i++)
  109.         if (strcmp(ident, kw[i].ident) == 0) {
  110.             return(kw[i].symbol);
  111.         }
  112.     return(ident_sym);
  113. } /*is_keyword*/
  114.  
  115.  
  116. /****************************************************************************/
  117. /*.doc next_char(internal)*/
  118. /*+
  119.   Delivers the next character from the input stream. The character is
  120.   stored in 'ch', the pointer to the next character is 'ch_ptr'.
  121. -*/
  122. /****************************************************************************/
  123.  
  124.  
  125. static void
  126. /*FCN*/next_char()
  127. {
  128.     if (*ch_ptr != EOS) {
  129.         ch = ads_toupper(*ch_ptr++);
  130.     } else {
  131.         ch = ' ';
  132.         end_of_line = TRUE;
  133.     }
  134. } /*next_char*/
  135.  
  136.  
  137. /****************************************************************************/
  138. /*.doc number(internal)*/
  139. /*+
  140.   Parses the terminal symbol NUMBER.
  141. -*/
  142. /****************************************************************************/
  143.  
  144.  
  145. static void
  146. /*FCN*/number()
  147. {
  148.     char *sym_begin;
  149.     char num_str[MAX_SYMBOL_LENGTH+1];
  150.     int  sym_len;
  151.     int  success;
  152.  
  153.     if (cal_err)
  154.         return;
  155.  
  156.     cal_lex.sym = int_sym;
  157.     sym_begin   =  ch_ptr - 1;
  158.  
  159.     while (ads_isdigit(ch)) {
  160.         next_char();
  161.     }
  162.  
  163.     if (ch == '.') {
  164.         cal_lex.sym = real_sym;
  165.         next_char();
  166.         while (ads_isdigit(ch)) {
  167.             next_char();
  168.         }
  169.     }
  170.     if (ch == /*MSG0*/'E') {
  171.         cal_lex.sym = real_sym;
  172.         next_char();
  173.         if ((ch == '+') || (ch == '-'))
  174.             next_char();
  175.         if (!(ads_isdigit(ch))) {
  176.             error(1, NULL);
  177.             return;
  178.         }
  179.         do {
  180.             next_char();
  181.         } while (ads_isdigit(ch));
  182.     }
  183.  
  184.     sym_len = ch_ptr - sym_begin - 1;
  185.     if (end_of_line) {
  186.         sym_len++;
  187.     }
  188.     if (sym_len > MAX_SYMBOL_LENGTH) {
  189.         sym_len = MAX_SYMBOL_LENGTH;
  190.     }
  191.  
  192.     strncpy(num_str, sym_begin, sym_len);
  193.     num_str[sym_len] = EOS;
  194.  
  195.     success = sscanf(num_str, "%lf", &cal_lex.real_num);
  196.     if (success != 1) {
  197.         error(1, num_str);
  198.         return;
  199.     }
  200.     if ((errno == ERANGE) || (errno == EDOM) ||
  201.         (cal_lex.real_num == HUGE_VAL)) {
  202.  
  203.         error(1, num_str);
  204.         return;
  205.     }
  206.     if ((cal_lex.sym == int_sym) &&
  207.         ((cal_lex.real_num > 32767) || (cal_lex.real_num < -32768))) {
  208.         error(3, NULL);
  209.         return;
  210.     }
  211. } /*number*/
  212.  
  213.  
  214. /****************************************************************************/
  215. /*.doc number_angle_or_feet(internal)*/
  216. /*+
  217.   Parses the terminal symbols NUMBER, ANGLE and FEET-INCHES.
  218. -*/
  219. /****************************************************************************/
  220.  
  221.  
  222. static void
  223. /*FCN*/number_angle_or_feet()
  224. {
  225.     if (cal_err)
  226.         return;
  227.  
  228.     number();
  229.     if (cal_err)
  230.         return;
  231.  
  232.     if (ch == /*MSG0*/'G') {                  /*grads*/
  233.         cal_lex.sym      = real_sym;
  234.         cal_lex.real_num = cal_lex.real_num * 0.9;
  235.         next_char();
  236.  
  237.     } else if (ch == /*MSG0*/'R') {           /*radians*/
  238.         cal_lex.sym      = real_sym;
  239.         cal_lex.real_num = cal_lex.real_num / DEGRAD;
  240.         next_char();
  241.  
  242.     } else if (ch == /*MSG0*/'D') {           /*<deg>d<min>'<sec>"*/
  243.         double deg, min, sec;
  244.  
  245.         deg = cal_lex.real_num;
  246.         min = sec = 0.0;
  247.  
  248.         next_char();
  249.         if (!ads_isdigit(ch)) {
  250.             goto End_degminsec;
  251.         }
  252.         number();
  253.  
  254.         if (ch == '\'') {
  255.             min = cal_lex.real_num;
  256.             next_char();
  257.             if (!ads_isdigit(ch)) {
  258.                 goto End_degminsec;
  259.             }
  260.             number();
  261.         }
  262.  
  263.         if (ch == '"') {
  264.             sec = cal_lex.real_num;
  265.             next_char();
  266.         } else {
  267.             error(34, NULL);
  268.             return;
  269.         }
  270.  
  271. End_degminsec:
  272.         if (cal_err)
  273.             return;
  274.  
  275.         cal_lex.sym      = real_sym;
  276.         cal_lex.real_num = deg + min / 60.0 + sec / 3600.0;
  277.  
  278.     } else if ((ch == '\'') || (ch == '"')) { /*<feet>'<inches>"*/
  279.         double feet = 0, inches = 0;
  280.         
  281.         if (ch == '\'') {
  282.             feet = cal_lex.real_num;
  283.  
  284.             next_char();
  285.             if (ch == '-') {
  286.                 next_char();
  287.             }
  288.  
  289.             if (ads_isdigit(ch)) {
  290.                 number();
  291.                 if (ch != '"') {
  292.                     error(22, NULL);
  293.                     return;
  294.                 }
  295.                 inches = cal_lex.real_num;
  296.                 next_char();
  297.             }
  298.         } else {
  299.             inches = cal_lex.real_num;
  300.             next_char();
  301.         }
  302.         
  303.         if (cal_err)
  304.             return;
  305.         
  306.         cal_lex.sym      = real_sym;
  307.         cal_lex.real_num = 12 * feet + inches;
  308.     } /*if*/
  309.  
  310. } /*number_angle_or_feet*/
  311.  
  312.  
  313. /****************************************************************************/
  314. /*.doc cal_next_symbol(internal)*/
  315. /*+
  316.   Delivers the next symbol from the input stream. The returned symbol 
  317.   is stored in the global structure 'cal_lex'.
  318. -*/
  319. /****************************************************************************/
  320.  
  321.  
  322. void
  323. /*FCN*/cal_next_symbol()
  324. {
  325.     char         *sym_begin;
  326.     int          sym_len;
  327.     register int i;
  328.  
  329.     if (cal_err)
  330.         return;
  331.  
  332.     while ((ch == ' ') && !end_of_line) {
  333.         next_char();
  334.     }
  335.  
  336.     if (ch == ' ') {
  337.         cal_lex.sym = no_sym;
  338.  
  339.     } else if (ads_isalpha(ch)) {
  340.  
  341.         cal_lex.sym = ident_sym;
  342.         sym_begin   = ch_ptr - 1;
  343.  
  344.         do {
  345.             next_char();
  346.         } while (ads_isalnum(ch) || (ch == '_'));
  347.  
  348.         sym_len = ch_ptr - sym_begin - 1;
  349.         if (end_of_line) {
  350.             sym_len++;
  351.         }
  352.         if (sym_len > MAX_SYMBOL_LENGTH) {
  353.             sym_len = MAX_SYMBOL_LENGTH;
  354.         }
  355.  
  356.         strncpy(cal_lex.id, sym_begin, sym_len);
  357.         cal_lex.id[sym_len] = EOS;
  358.         str_toupper(cal_lex.id);
  359.  
  360.         /* Is it a keyword ? */
  361.  
  362.         cal_lex.sym = is_keyword(cal_lex.id);
  363.         if (cal_lex.sym != ident_sym)
  364.             return;
  365.  
  366.         /* Is it a function name? */
  367.  
  368.         for (i = 0; i < cal_funcs_number; i++) {
  369.             if (strcmp(cal_lex.id, cal_funcs_table[i].name) == 0) {
  370.                 cal_lex.sym      = func_sym;
  371.                 cal_lex.func_ptr = cal_funcs_table[i].func;
  372.                 return;
  373.             } /*if*/
  374.         } /*for*/
  375.  
  376.     } else if (ch == '\'') {
  377.         /* The name of AutoLISP symbol enclosed in apostrophes */
  378.         
  379.         cal_lex.sym = ident_sym;
  380.         next_char();
  381.         
  382.         i = 0;
  383.         while (!end_of_line && (i < MAX_SYMBOL_LENGTH) && (ch != '\'')) {
  384.             cal_lex.id[i++] = ch;
  385.             next_char();
  386.         }
  387.         cal_lex.id[i] = EOS;
  388.  
  389.         if (end_of_line) {
  390.             error(9, NULL);
  391.             return;
  392.         } if (ch != '\'') {
  393.             error(31, cal_lex.id);
  394.             return;
  395.         }
  396.         
  397.         next_char();
  398.  
  399.     } else if (ads_isdigit(ch) || (ch == '.')) {
  400.         number_angle_or_feet();
  401.  
  402.     } else if (ch == '[') { cal_lex.sym = lbracket_sym;  next_char(); }
  403.     else   if (ch == ']') { cal_lex.sym = rbracket_sym;  next_char(); }
  404.     else   if (ch == ',') { cal_lex.sym = comma_sym;     next_char(); }
  405.     else   if (ch == '-') { cal_lex.sym = minus_sym;     next_char(); }
  406.     else   if (ch == '+') { cal_lex.sym = plus_sym;      next_char(); }
  407.     else   if (ch == '*') { cal_lex.sym = asterisk_sym;  next_char(); }
  408.     else   if (ch == '/') { cal_lex.sym = slash_sym;     next_char(); }
  409.     else   if (ch == '(') { cal_lex.sym = lparent_sym;   next_char(); }
  410.     else   if (ch == ')') { cal_lex.sym = rparent_sym;   next_char(); }
  411.     else   if (ch == '^') { cal_lex.sym = caret_sym;     next_char(); }
  412.     else   if (ch == '@') { cal_lex.sym = at_sym;        next_char(); }
  413.     else   if (ch == '<') { cal_lex.sym = lessthan_sym;  next_char(); }
  414.     else   if (ch == '&') { cal_lex.sym = ampersand_sym; next_char(); }
  415.     else   if (ch == '=') { cal_lex.sym = equal_sym;     next_char(); }
  416.     else {
  417.         cal_lex.id[0] = ch;
  418.         cal_lex.id[1] = EOS;
  419.         error(2, cal_lex.id);
  420.         return;
  421.     }
  422.  
  423. } /*cal_next_symbol*/
  424.  
  425.  
  426. /****************************************************************************/
  427. /*.doc cal_lex_start(external)*/
  428. /*+
  429.   Initializes the lexical analyser with the input string 'line'. Reads the 
  430.   first symbol ahead.
  431. -*/
  432. /****************************************************************************/
  433.  
  434.  
  435. void
  436. /*FCN*/cal_lex_start(line)
  437.  
  438.   char *line;
  439. {
  440.     cal_err     = 0;
  441.     errno       = 0;
  442.     ch          = ' ';
  443.     ch_ptr      = line;
  444.     end_of_line = FALSE;
  445.     next_char();
  446.     cal_next_symbol();
  447. } /*cal_lex_start*/
  448.  
  449.